﻿using System.Windows;
using System.Windows.Input;
using Microsoft.Surface.Presentation.Controls;
using System.Windows.Controls;
using Microsoft.Surface.Presentation.Manipulations;
using System.Windows.Media;

namespace WinwiseARDrone.SurfaceV1Client.Controls
{
    /// <summary>
    /// Contrôle d'affichage du menu Emergency
    /// </summary>
    [TemplatePart(Name = "PART_btnReset", Type = typeof(SurfaceButton))]
    [TemplatePart(Name = "PART_btnHide", Type = typeof(SurfaceButton))]
    [TemplatePart(Name = "PART_grdItem", Type = typeof(Grid))]
    public partial class EmergencyControl : SurfaceControl
    {
        #region Propriétés de dépendance

        public static readonly DependencyProperty CommandResetProperty = DependencyProperty.Register("CommandReset", typeof(ICommand), typeof(EmergencyControl), new UIPropertyMetadata(null, new PropertyChangedCallback(EmergencyControl.OnCommandResetChanged)));

        #endregion

        #region Accesseurs

        /// <summary>
        /// Obtient ou définit la commande exécuté lors du réset
        /// </summary>
        public ICommand CommandReset
        {
            get
            {
                return ((ICommand)this.GetValue(EmergencyControl.CommandResetProperty));
            }
            set
            {
                this.SetValue(EmergencyControl.CommandResetProperty, value);
            }
        }

        #endregion

        #region Variables d'instances

        private bool m_bProcessing;
        private Grid m_oItem;
        private SurfaceButton m_oButtonReset;
        private SurfaceButton m_oButtonHide;
        private Affine2DManipulationProcessor m_oProcessor;

        #endregion

        #region Constructeurs

        /// <summary>
        /// Constructeur statique de la classe
        /// </summary>
        static EmergencyControl()
        {
            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(EmergencyControl), new FrameworkPropertyMetadata(typeof(EmergencyControl)));
        }

        /// <summary>
        /// Constructeur de la classe
        /// </summary>
        public EmergencyControl()
        {
            this.m_bProcessing = false;
            this.m_oButtonReset = null;

            // Création du processor

            this.m_oProcessor = new Affine2DManipulationProcessor(Affine2DManipulations.TranslateX | Affine2DManipulations.TranslateY, this);
            this.m_oProcessor.Affine2DManipulationCompleted += new System.EventHandler<Affine2DOperationCompletedEventArgs>(this.Affine2DManipulationCompleted);
            this.m_oProcessor.Affine2DManipulationDelta += new System.EventHandler<Affine2DOperationDeltaEventArgs>(this.Affine2DManipulationDelta);
            this.m_oProcessor.Affine2DManipulationStarted += new System.EventHandler<Affine2DOperationStartedEventArgs>(this.Affine2DManipulationStarted);
        }

        #endregion

        #region Fonctions publiques

        /// <summary>
        /// Se produit sur la mise ne place du template
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // Récupération de l'item

            this.m_oItem = (Grid)this.Template.FindName("PART_grdItem", this);

            // On va chercher les bouttons

            this.m_oButtonHide = (SurfaceButton)this.Template.FindName("PART_btnHide", this);
            this.m_oButtonHide.Click += new RoutedEventHandler(this.ButtonHideClick);

            this.m_oButtonReset = (SurfaceButton)this.Template.FindName("PART_btnReset", this);
            this.m_oButtonReset.Command = this.CommandReset;

            // On se branche sur les contacts

            this.ContactDown += new Microsoft.Surface.Presentation.ContactEventHandler(this.EmergencyControlContactDown);
        }

        #endregion

        #region Fonctions protégées

        /// <summary>
        /// Se produit sur un changmenent de la propriété CommandReset
        /// </summary>
        /// <param name="p_oOld">Ancienne valeur</param>
        /// <param name="p_oNew">Nouvelle valeur</param>
        protected virtual void OnCommandResetChanged(ICommand p_oOld, ICommand p_oNew)
        {
            if (this.m_oButtonReset != null)
                this.m_oButtonReset.Command = p_oNew;
        }

        #endregion

        #region Fonctions privées

        /// <summary>
        /// Se produit sur la fin de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationCompleted(object sender, Affine2DOperationCompletedEventArgs e)
        {
            this.m_bProcessing = false;
            this.m_oItem.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// Se produit sur le delta de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
        {
            Canvas.SetLeft(this.m_oItem, Canvas.GetLeft(this.m_oItem) + e.Delta.X);
            Canvas.SetTop(this.m_oItem, Canvas.GetTop(this.m_oItem) + e.Delta.Y);
        }

        /// <summary>
        /// Se produit sur le début de la manipulation
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Affine2DManipulationStarted(object sender, Affine2DOperationStartedEventArgs e)
        {
            this.m_bProcessing = true;

            Canvas.SetLeft(this.m_oItem, e.ManipulationOrigin.X - 120);
            Canvas.SetTop(this.m_oItem, e.ManipulationOrigin.Y - 50);
         
            this.m_oItem.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Se produit sur l'appuie du bouton Non
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void ButtonHideClick(object sender, RoutedEventArgs e)
        {
            this.m_oProcessor.CompleteManipulation();
        }

        /// <summary>
        /// Se produit sur un contact sur le contrôle
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void EmergencyControlContactDown(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {
            if (!this.m_bProcessing && e.Contact.IsTagRecognized)
                this.m_oProcessor.BeginTrack(e.Contact);
        }

        #endregion

        #region Fonctions statiques privées

        /// <summary>
        /// Se produit sur le changement de la propriété CommandReset
        /// </summary>
        /// <param name="p_oItem">Objet de dépendance</param>
        /// <param name="p_oArgs">Argument de l'appel</param>
        private static void OnCommandResetChanged(DependencyObject p_oItem, DependencyPropertyChangedEventArgs p_oArgs)
        {
            (p_oItem as EmergencyControl).OnCommandResetChanged((ICommand)p_oArgs.OldValue, (ICommand)p_oArgs.NewValue);
        }

        #endregion
    }
}
